﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Xml;
using Microsoft.Office.Tools.Ribbon;
using Visio = Microsoft.Office.Interop.Visio;

namespace SandcastleVisioAddin
{
    public partial class Ribbon1 : RibbonBase
    {
        string dia_path = @"C:\Users\Robos_\Documents\Visual Studio 2010\Projects\SHFBDiagram\SHFB_Test\" + "Diagrams";

        private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
        {
            Globals.ThisAddIn.Application.DocumentCreated +=
                new Visio.EApplication_DocumentCreatedEventHandler(Application_DocumentCreated);
            Globals.ThisAddIn.Application.PageChanged +=
                new Visio.EApplication_PageChangedEventHandler(Application_PageChanged);
            Globals.ThisAddIn.Application.DocumentOpened += 
                new Visio.EApplication_DocumentOpenedEventHandler(Application_DocumentOpened);

            editBox1.Text = dia_path;

            if (Globals.ThisAddIn.Application.ActivePage == null)
                EnableInterface(false);
            else
            {
                EnableInterface(true);
                editBox2.Text = GetCurrentDName();
            }
        }

        void Application_DocumentOpened(Visio.Document Doc)
        {
            if (Globals.ThisAddIn.Application.ActivePage == null)
                EnableInterface(false);
            else
            {
                EnableInterface(true);
                editBox2.Text = GetCurrentDName();
            }
        }

        void Application_PageChanged(Visio.Page Page)
        {
            editBox2.Text = Globals.ThisAddIn.Application.ActiveDocument.ID.ToString().Trim() + "_" + Page.ID.ToString().Trim() + "_CLICK";
            this.RibbonUI.InvalidateControl(editBox2.Id);
            editBox2.RibbonUI.InvalidateControl(editBox2.Id);
        }

        void Application_DocumentCreated(Visio.Document Doc)
        {
            if (Globals.ThisAddIn.Application.ActivePage == null)
                EnableInterface(false);
            else
            {
                EnableInterface(true);
                editBox2.Text = GetCurrentDName();
            }

            //throw new NotImplementedException();
        }

        private void button1_Click(object sender, RibbonControlEventArgs e)
        {
            if (dia_path != this.editBox1.Text)
                dia_path = this.editBox1.Text.Trim() + @"\Diagrams";

            if (!Directory.Exists(dia_path))
            {
                MessageBox.Show("Путь проекта не существует!");
                return;
            }

            Globals.ThisAddIn.Application.ActivePage.Export(dia_path + @"\" + GetCurrentDName() + ".jpg");

            DirectoryInfo di = Directory.CreateDirectory(dia_path + @"\" + GetCurrentDName());

            if (di != null)
            {
                List<ImgClass> shapes = new  List<ImgClass>(Globals.ThisAddIn.Application.ActivePage.Shapes.Count);
                foreach (Visio.Shape shape in Globals.ThisAddIn.Application.ActivePage.Shapes)
                {
                    ImgClass imgC = new ImgClass("","","",0);
                    if (IterateCellsInShape(shape, imgC))
                    {
                        shape.Export(di.FullName + @"\shape_" + GetCurrentDName() + "_" + shape.ID + ".jpg");
                        shapes.Add(imgC);
                    }         
                }
                CreateXMLDiagram(dia_path + @"\" + GetCurrentDName() + ".cd", shapes.ToArray());
            }
            MessageBox.Show("Экспорт закончен. Обработано " + Globals.ThisAddIn.Application.ActivePage.Shapes.Count + " элемента(ов).");
        }

        #region XML Diagram
        void CreateXMLDiagram(string fileName, ImgClass[] shapes)
        {
            XmlDocument diaDoc = new XmlDocument();

            XmlDeclaration dec = diaDoc.CreateXmlDeclaration("1.0", "utf-8", null);
            diaDoc.AppendChild(dec);

            XmlElement classElems = diaDoc.CreateElement("ClassDiagram");

            foreach (ImgClass shp in shapes)
            {
                XmlElement classElem = diaDoc.CreateElement("Class");
                XmlAttribute nameAttr = diaDoc.CreateAttribute("Name");

                nameAttr.Value = shp.className;

                classElem.Attributes.Append(nameAttr);

                classElems.AppendChild(classElem);

                XmlElement posElem = diaDoc.CreateElement("Position");
                XmlAttribute
                    xAttr = diaDoc.CreateAttribute("X"),
                    yAttr = diaDoc.CreateAttribute("Y"),
                    wAttr = diaDoc.CreateAttribute("Width"),
                    hAttr = diaDoc.CreateAttribute("Height");

                xAttr.Value = shp.X.ToString().Replace(',', '.');
                yAttr.Value = shp.Y.ToString().Replace(',', '.');
                wAttr.Value = shp.width.ToString().Replace(',', '.');
                hAttr.Value = shp.height.ToString().Replace(',', '.');

                posElem.SetAttributeNode(xAttr);
                posElem.SetAttributeNode(yAttr);
                posElem.SetAttributeNode(wAttr);
                posElem.SetAttributeNode(hAttr);

                classElem.AppendChild(posElem);
            }

            diaDoc.AppendChild(classElems);

            try
            {
                diaDoc.Save(fileName);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        #endregion

        #region Shape Sheet Util
        ////////////////////////////////////--------Shape Sheet----------//////////////////////////////////////////

        private bool IterateCellsInShape(
            Microsoft.Office.Interop.Visio.Shape targetShape, ImgClass imgc)
        {

            bool returnValue = false;

            try
            {

                // Iterate through the Shape Transform section.
                returnValue = iterateShapeTransform(targetShape, imgc);

                if (returnValue)
                {

                    // Iterate through the Custom Properties section.
                    returnValue = iterateCustomProperties(targetShape, imgc);
                }

                if (returnValue)
                {

                    // Iterate through each Geometry section.
                    returnValue = iterateGeometry(targetShape, imgc);
                }
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine(err.Message);
                throw;
            }

            if (returnValue)
                imgc.Transform();

            return returnValue;
        }

        /// <summary>This method iterates through the Shape Transform section.
        /// </summary>
        /// <param name="targetShape">Reference to the shape that will be used
        /// </param>
        /// <returns>true if successful, otherwise false</returns>
        private bool iterateShapeTransform(
            Microsoft.Office.Interop.Visio.Shape targetShape, ImgClass imgct)
        {

            short sectionIndex;
            bool returnValue = false;

            try
            {

                // Iterate through the Shape Transform section.
                sectionIndex = (short)Microsoft.Office.Interop.Visio.
                    VisSectionIndices.visSectionObject;
                System.Diagnostics.Debug.WriteLine(
                    "\r\nSHAPE TRANSFORM SECTION");
                returnValue = iterateSection(targetShape,
                    sectionIndex, imgct);
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine(err.Message);
                throw;
            }

            return returnValue;
        }

        /// <summary>This method iterates through the Custom Properties section.
        /// </summary>
        /// <param name="targetShape">Reference to the shape that will be used
        /// </param>
        /// <returns>true if successful, otherwise false</returns>
        private bool iterateCustomProperties(
            Microsoft.Office.Interop.Visio.Shape targetShape, ImgClass imgcp)
        {

            short sectionIndex;
            bool returnValue = false;

            try
            {

                // Iterate through the Custom Properties section.
                sectionIndex = (short)Microsoft.Office.Interop.Visio.
                    VisSectionIndices.visSectionProp;

                // See if the Custom Properties section exists
                if (0 != targetShape.get_SectionExists(sectionIndex,
                    (short)Microsoft.Office.Interop.Visio.
                    VisExistsFlags.visExistsAnywhere))
                {

                    System.Diagnostics.Debug.WriteLine(
                        "\r\nCUSTOM PROPERTIES SECTION");
                    returnValue = iterateSection(targetShape,
                        sectionIndex, imgcp);
                }
                else
                {

                    returnValue = true;
                }
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine(err.Message);
                throw;
            }

            return returnValue;
        }

        /// <summary>This method iterates through each Geometry section.
        /// </summary>
        /// <param name="targetShape">Reference to the shape that will be used
        /// </param>
        /// <returns>true if successful, otherwise false</returns>
        private bool iterateGeometry(
            Microsoft.Office.Interop.Visio.Shape targetShape, ImgClass imgcg)
        {

            short sectionIndex;
            short sectionCount;
            bool returnValue = false;

            try
            {

                sectionCount = targetShape.GeometryCount;

                //imgcg.gData = new ImgClass.GEOMDATA[sectionCount];

                returnValue = true;

                // Iterate through each Geometry section.
                for (short geometrySection = 0;
                    geometrySection < sectionCount && returnValue;
                    geometrySection++)
                {

                    // Get the section index of the current Geometry
                    // section.
                    sectionIndex = (short)(
                        (short)Microsoft.Office.Interop.Visio.
                            VisSectionIndices.visSectionFirstComponent +
                        geometrySection);
                    System.Diagnostics.Debug.WriteLine(
                        "\r\nGEOMETRY SECTION");
                    returnValue = iterateSection(targetShape,
                        sectionIndex, imgcg);
                }
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine(err.Message);
                throw;
            }

            return returnValue;
        }

        /// <summary>This method iterates through the section specified in
        /// the sectionIndex parameter for a given shape and displays the
        /// universal name, formula, and value for each cell in the debug
        /// window.</summary>
        /// <param name="targetShape">Reference to the shape that will be used
        /// </param>
        /// <param name="sectionIndex">Index of the section that is to be
        /// iterated</param>
        /// <returns>true if successful, otherwise false</returns>
        private bool iterateSection(
            Microsoft.Office.Interop.Visio.Shape targetShape,
            short sectionIndex, ImgClass iimgc)
        {

            Microsoft.Office.Interop.Visio.Section currentSection;
            Microsoft.Office.Interop.Visio.Cell currentCell;
            short rowCount;
            short cellCount;
            string cellFormula;
            bool returnValue = false;

            try
            {
                // Get the row count for this section.
                currentSection = targetShape.get_Section(sectionIndex);
                rowCount = targetShape.get_RowCount(sectionIndex);

                switch (sectionIndex)
                {
                    case (short)Microsoft.Office.Interop.Visio.
                    VisSectionIndices.visSectionObject:
                        {
                            iimgc.trans_data = new ImgClass.TRANS_DATA();
                            break;
                        }
                    case (short)Microsoft.Office.Interop.Visio.
                    VisSectionIndices.visSectionProp:
                        {
                            iimgc.className = "Undefined_element";
                            break;
                        }
                    case (short)Microsoft.Office.Interop.Visio.
                    VisSectionIndices.visSectionFirstComponent:
                        break;
                }

                // Iterate through each row in this section.
                for (short rowIndex = 0; rowIndex < rowCount; rowIndex++)
                {

                    cellCount = targetShape.get_RowsCellCount(sectionIndex,
                        rowIndex);
                    if (cellCount == 0)
                    {

                        cellCount = targetShape.get_RowsCellCount(sectionIndex,
                            ++rowIndex);
                    }

                    // Get each of the cells in this section.
                    for (short cellIndex = 0; cellIndex < cellCount;
                        cellIndex++)
                    {

                        currentCell = currentSection[rowIndex][cellIndex];
                        cellFormula = currentCell.FormulaU;

                        // Replace empty formula strings with "No Formula"
                        if (0 == cellFormula.Length)
                        {
                            cellFormula = "No Formula";
                        }

                        // Output the cell to the debug window
                        System.Diagnostics.Debug.WriteLine(currentCell.Name +
                            " - Formula: " + cellFormula +
                            ", Value: " +
                            currentCell.get_ResultStr(currentCell.Units));

                        switch(sectionIndex)
                        {
                            case (short)Microsoft.Office.Interop.Visio.
                            VisSectionIndices.visSectionObject:
                                    SetTransformData(iimgc, currentCell.Name, currentCell.get_Result(Microsoft.Office.
							Interop.Visio.VisUnitCodes.visInches));
                                    break;
                            case (short)Microsoft.Office.Interop.Visio.
                            VisSectionIndices.visSectionProp:
                                        SetPropertiesData(iimgc, currentCell.Name, currentCell.get_ResultStr(Microsoft.Office.
                                    Interop.Visio.VisUnitCodes.visNoCast), targetShape);
                                        break;
                            case (short)Microsoft.Office.Interop.Visio.
                            VisSectionIndices.visSectionFirstComponent:
                                //SetGeometryData(iimgc, currentCell.Name, currentCell.get_ResultStr(GraphicsUnit.Display), targetShape.GeometryCount);
                                break; 
                        }
                    }
                }

                returnValue = true;
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.WriteLine(err.Message);
                throw;
            }

            return returnValue;
        }


        //////////////////////////////////////------------Get_CustomProperty----------////////////////////////////////////////////////
        public string ReadANamedCustomProperty(
            Microsoft.Office.Interop.Visio.Shape customPropertyShape,
            string cellName, bool isLocalName)
        {

            if (customPropertyShape == null || cellName == null)
            {
                return null;
            }

            const string CUST_PROP_PREFIX = "Prop.";

            Microsoft.Office.Interop.Visio.Application visioApplication =
                (Microsoft.Office.Interop.Visio.Application)
                customPropertyShape.Application;

            string propName;
            Microsoft.Office.Interop.Visio.Cell customPropertyCell = null;

            try
            {

                // Verify that all incoming string parameters are not of zero 
                // length, except for the ones that have default values as ""
                // and the output parameters.
                if (cellName.Length == 0)
                {

                    throw new System.ArgumentNullException("cellName",
                        "Zero length string input.");
                }

                // Custom properties have a prefix of "Prop".
                propName = CUST_PROP_PREFIX + cellName;

                // If the custom property exists, get the value of the cell from
                // the shape.
                if (isLocalName)
                {
                    if (customPropertyShape.get_CellExists(propName,
                        (short)Microsoft.Office.Interop.Visio.VisExistsFlags.
                        visExistsAnywhere) != 0)
                    {

                        // If the cell exists, the cell variable gets a
                        // valid value
                        customPropertyCell = customPropertyShape.get_Cells(
                            propName);
                    }
                }
                else if (customPropertyShape.get_CellExistsU(propName,
                    (short)Microsoft.Office.Interop.Visio.VisExistsFlags.
                    visExistsAnywhere) != 0)
                {

                    // If the cell exists, the cell variable gets a
                    // valid value
                    customPropertyCell = customPropertyShape.get_CellsU(
                        propName);
                }

                // Only display message boxes if the AlertResponse is 0.
                if (visioApplication.AlertResponse == 0)
                {

                    // Proceed if the property exists.
                    if (customPropertyCell == null)
                    {

                        return "Not_Found";
                    }
                    else
                    {

                        //// Show the value in page units.
                        //System.Windows.Forms.MessageBox.Show(propName +
                        //    ".Result in Page Units = " +
                        //    customPropertyCell.get_ResultStr(Microsoft.Office.
                        //    Interop.Visio.VisUnitCodes.visPageUnits));

                       return customPropertyCell.get_ResultStr(
                            Microsoft.Office.Interop.Visio.VisUnitCodes.visNoCast);

                        //// Show the value in inches.
                        //System.Windows.Forms.MessageBox.Show(propName +
                        //    ".Result in Inches = " +
                        //    customPropertyCell.get_Result(Microsoft.Office.
                        //    Interop.Visio.VisUnitCodes.visInches));

                        //// Show the value using no cast.
                        //System.Windows.Forms.MessageBox.Show(propName +
                        //    ".Result using No Cast = " +
                        //    customPropertyCell.get_Result(Microsoft.Office.
                        //    Interop.Visio.VisUnitCodes.visNoCast));

                        //// Show the formula attached to the custom property.
                        //System.Windows.Forms.MessageBox.Show(propName +
                        //    " FormulaU = " + customPropertyCell.FormulaU);
                    }
                }
                return "Not_Found";
            }
            catch (Exception err)
            {
                System.Windows.Forms.MessageBox.Show(err.Message);
                throw;
            }
        }
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        
        #endregion

        #region Utils

        private void SetTransformData(ImgClass iclss, string cellName, double cellValue)
        {
            //if ((cellValue.LastIndexOf(' ') != -1) && (cellValue.LastIndexOf(' ') != 0))
            //    cellValue = cellValue.Substring(0, cellValue.LastIndexOf(' '));
            //else
            //    cellValue = "0.0";

            switch (cellName.Trim())
            {
                case "PinX":
                    iclss.trans_data.tPinX = cellValue;
                    break;
                case "PinY":
                    iclss.trans_data.tPinY = cellValue;
                    break;
                case "Width":
                    iclss.trans_data.tWidth = cellValue;
                    break;
                case "Height":
                    iclss.trans_data.tHeight = cellValue;
                    break;
                case "LocPinX":
                    iclss.trans_data.tLocPinX = cellValue;
                    break;
                case "LocPinY":
                    iclss.trans_data.tLocPinY = cellValue;
                    break;
            }
        }

        private void SetPropertiesData(ImgClass iclss, string cellName, string cellValue, Microsoft.Office.Interop.Visio.Shape tshape)
        {
            if (cellValue.Trim() == "TopicLink")
                iclss.className = ReadANamedCustomProperty
                                                        (
                                                            tshape, 
                                                            cellName.Substring(5, cellName.IndexOf('.', 5)-5),
                                                            false
                                                        ).Trim()
                    ;
        }

        private void SetGeometryData(ImgClass iclss, string cellName, string cellValue, int gCount)
        {
            //switch (cellName.Trim())
            //{
            //    case "Geometry.X1":
            //        iclss.gData[gCount].xGeom[1] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.X2":
            //        iclss.gData[gCount].xGeom[2] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.X3":
            //        iclss.gData[gCount].xGeom[3] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.X4":
            //        iclss.gData[gCount].xGeom[4] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.X5":
            //        iclss.gData[gCount].yGeom[5] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.Y1":
            //        iclss.gData[gCount].yGeom[1] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.Y2":
            //        iclss.gData[gCount].yGeom[2] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.Y3":
            //        iclss.gData[gCount].yGeom[3] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.Y4":
            //        iclss.gData[gCount].yGeom[4] = Convert.ToDouble(cellValue);
            //        break;
            //    case "Geometry.Y5":
            //        iclss.gData[gCount].yGeom[5] = Convert.ToDouble(cellValue);
            //        break;
            //}
        }

        private void EnableInterface(bool state)
        {
            if (state)
            {
                foreach (RibbonControl ribcon in group1.Items)
                {
                    ribcon.Enabled = true;
                }
            }
            else
            {
                foreach (RibbonControl ribcon in group1.Items)
                {
                    ribcon.Enabled = false;
                }
            }
        }

        private string GetCurrentDName()
        {
            //System.Windows.Forms.MessageBox.Show("Actvie document is " + Application.ActiveDocument.Name + Environment.NewLine +
            //    " Actvie page is " + Application.ActivePage.NameU);
            return Globals.ThisAddIn.Application.ActiveDocument.ID.ToString().Trim() + "_" + Globals.ThisAddIn.Application.ActivePage.ID.ToString().Trim() + "_CLICK";
        }

        #endregion
    }
}
